package com.ly.heart.service.king;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.gson.Gson;
import com.kingdee.bos.webapi.entity.IdentifyInfo;
import com.kingdee.bos.webapi.entity.RepoRet;
import com.kingdee.bos.webapi.sdk.K3CloudApi;
import com.ly.common.exception.CustomException;
import com.ly.common.utils.erp.CommonUtil;
import com.ly.common.utils.erp.KingConstUtil;
import com.ly.heart.domain.KingFinancePayEntity;
import com.ly.heart.domain.KingFinancePayDetailEntity;
import com.ly.heart.domain.KingOrgEntity;
import com.ly.heart.domain.king.BaseChildBo;
import com.ly.heart.domain.king.invoice.PayBo;
import com.ly.heart.domain.king.invoice.PayDetail;
import com.ly.heart.domain.request.KingBaseSingleRequest;
import com.ly.heart.domain.response.KingBaseResponse;
import com.ly.heart.domain.response.KingBaseResponseError;
import com.ly.heart.domain.response.KingBaseResponseSuccessEntity;
import com.ly.heart.service.IKingFinancePayDetailService;
import com.ly.heart.service.IKingFinancePayService;
import com.ly.heart.service.IKingOrgService;
import com.ly.heart.util.CurrentUserUtil;
import com.ly.heart.util.KingCommonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author: Wuzh
 * @Description:
 * @Date Created in 16:05 2024-07-20
 * @return
 */
@Component
@Slf4j
public class PayPushService {

    @Resource
    private IKingFinancePayService iKingFinancePayService;
    @Resource
    private IKingFinancePayDetailService iKingFinancePayDetailService;
    @Resource
    private IKingOrgService iKingOrgService;

    public void push (KingFinancePayEntity kingFinancePayEntity) {
        KingOrgEntity orgEntity = iKingOrgService.getOne ( new LambdaQueryWrapper<KingOrgEntity> ().eq ( KingOrgEntity :: getOrgId, CurrentUserUtil.getCompanyId () ).eq ( KingOrgEntity :: getIsDisabled, true ) );
        if ( orgEntity == null ) {
            throw new CustomException ( "请先至系统管理中配置金蝶账套！" );
        }
        IdentifyInfo identifyInfo = KingCommonUtil.getIdentifyInfo ( orgEntity );
        K3CloudApi client = new K3CloudApi ( identifyInfo );
        log.info ( "付款单调用金蝶下推->{}", kingFinancePayEntity );
        if ( ObjectUtils.isEmpty ( kingFinancePayEntity ) ) {
            throw new CustomException ( "付款单对象为空" );
        }
        if ( kingFinancePayEntity.getIsSend () == KingConstUtil.KING_DATA_IS_SEND_YES ) {
            throw new CustomException ( "该单据已推送金蝶，无需重复推送！" );
        }
        PayBo payBo = assemblePay ( kingFinancePayEntity );
        try {
            save ( payBo, client );
            submit ( payBo, client );
            audit ( payBo, client );
            updateSendSuccess ( kingFinancePayEntity.getId () );
        } catch ( Exception e ) {
            e.printStackTrace ();
            throw new CustomException ( "付款单推送失败，请稍后重试！" );
        }
    }

    /**
     * 推送付款单到金蝶
     * @param bo
     * @param client
     * @throws Exception
     */
    private void save (PayBo bo, K3CloudApi client) throws Exception {
        KingBaseSingleRequest singleRequest = new KingBaseSingleRequest ();
        singleRequest.setModel ( bo );
        String s = JSONObject.toJSONString ( singleRequest );
        log.info ( "付款单转JSON->{}", s );
        String resultJson = client.save ( KingConstUtil.AP_PAYBILL, s );
        Gson gson = new Gson ();
        //对返回结果进行解析和校验
        RepoRet repoRet = gson.fromJson ( resultJson, RepoRet.class );
        KingBaseResponse baseResponse = JSONObject.parseObject ( gson.toJson ( repoRet.getResult ().getResponseStatus () ), KingBaseResponse.class );
        StringBuilder sb = new StringBuilder ();
        if ( baseResponse.getIsSuccess () ) {
            List<KingBaseResponseSuccessEntity> successEntities = baseResponse.getSuccessEntitys ();
            sb.append ( "付款单-编码为：【" );
            successEntities.forEach ( success -> {
                sb.append ( success.getNumber () ).append ( ";" );
            } );
            sb.append ( "】" );
            log.info ( "{} 推送成功", sb );

        } else {
            List<KingBaseResponseError> errors = baseResponse.getErrors ();
            errors.forEach ( err -> {
                sb.append ( err.getMessage () ).append ( ";" );
            } );
            throw new RuntimeException ( "付款单-推送失败：【" + sb + "】" );
        }
    }


    /**
     * 提交采购开票(应付单)到金蝶
     * @param bo
     * @param client
     */
    private void submit (PayBo bo, K3CloudApi client) throws Exception {
        List<String> strings = new ArrayList<> ();
        strings.add ( bo.getFBillNo () );
        bo.setNumbers ( strings );
        String jsonData = JSON.toJSONString ( bo );
        String resultJson = client.submit ( KingConstUtil.AP_PAYBILL, jsonData );
        Gson gson = new Gson ();
        //对返回结果进行解析和校验
        RepoRet repoRet = gson.fromJson ( resultJson, RepoRet.class );
        KingBaseResponse baseResponse = JSONObject.parseObject ( gson.toJson ( repoRet.getResult ().getResponseStatus () ), KingBaseResponse.class );
        StringBuilder sb = new StringBuilder ();
        if ( baseResponse.getIsSuccess () ) {
            //提交成功
            List<KingBaseResponseSuccessEntity> successEntities = baseResponse.getSuccessEntitys ();
            sb.append ( "付款单-编码为：【" );
            successEntities.forEach ( success -> {
                sb.append ( success.getNumber () ).append ( ";" );
            } );
            sb.append ( "】" );
            log.error ( "{} 提交成功", sb );
        } else {
            List<KingBaseResponseError> errors = baseResponse.getErrors ();
            errors.forEach ( err -> {
                sb.append ( err.getMessage () ).append ( ";" );
            } );
            throw new RuntimeException ( "付款单提交失败：【" + sb + "】" );
        }
    }

    /**
     * 审核应付单
     * @param bo
     * @param client
     */
    private void audit (PayBo bo, K3CloudApi client) throws Exception {
        List<String> strings = new ArrayList<> ();
        strings.add ( bo.getFBillNo () );
        bo.setNumbers ( strings );
        String jsonData = JSON.toJSONString ( bo );
        String resultJson = client.audit ( KingConstUtil.AP_PAYBILL, jsonData );
        Gson gson = new Gson ();
        //对返回结果进行解析和校验
        RepoRet repoRet = gson.fromJson ( resultJson, RepoRet.class );
        KingBaseResponse baseResponse = JSONObject.parseObject ( gson.toJson ( repoRet.getResult ().getResponseStatus () ), KingBaseResponse.class );
        StringBuilder sb = new StringBuilder ();
        if ( baseResponse.getIsSuccess () ) {
            //提交成功
            List<KingBaseResponseSuccessEntity> successEntities = baseResponse.getSuccessEntitys ();
            sb.append ( "付款单-编码为：【" );
            successEntities.forEach ( success -> {
                sb.append ( success.getNumber () ).append ( ";" );
            } );
            sb.append ( "】" );
            log.error ( "{} 审核成功", sb );
        } else {
            List<KingBaseResponseError> errors = baseResponse.getErrors ();
            errors.forEach ( err -> {
                sb.append ( err.getMessage () ).append ( ";" );
            } );
            throw new RuntimeException ( "付款单审核失败：【" + sb + "】" );
        }
    }

    private void updateSendSuccess (String id) {
        KingFinancePayEntity payEntity = new KingFinancePayEntity ();
        payEntity.setId ( id );
        payEntity.setIsSend ( KingConstUtil.KING_DATA_IS_SEND_YES );
        boolean b = iKingFinancePayService.updateById ( payEntity );
        if ( ! b ) {
            throw new CustomException ( "修改推送金蝶状态失败！" );
        }
    }

    /**
     * 组装付款业务对象
     * @param payEntity
     * @return
     */
    private PayBo assemblePay (KingFinancePayEntity payEntity) {
        PayBo bo = new PayBo ();
        //1.基础
        bo.setFBillNo ( payEntity.getDocNo () );
        //单据类型
        BaseChildBo billType = new BaseChildBo ().setFNumber ( payEntity.getDocTypeCode () );
        bo.setFBillTypeID ( billType );
        //收款单位类型
        bo.setFRECTUNITTYPE ( payEntity.getReceiptDeptType () );
        //付款组织
        BaseChildBo payOrgid = new BaseChildBo ().setFNumber ( payEntity.getPayDeptCode () );
        bo.setFPAYORGID ( payOrgid ).setFSETTLEORGID ( payOrgid ).setFPURCHASEORGID ( payOrgid );
        //收款单位
        BaseChildBo receiptDept = new BaseChildBo ().setFNumber ( payEntity.getReceiptDeptCode () );
        bo.setFRECTUNIT ( receiptDept );
        //业务日期
        bo.setFDATE ( CommonUtil.getDateStrFormat ( payEntity.getBusinessTime (), "yyyy-MM-dd HH:mm:ss" ) );
        //币别
        BaseChildBo currency = new BaseChildBo ().setFNumber ( payEntity.getKingBaseCurrencyCode () );
        bo.setFCURRENCYID ( currency );
        //往来单位类型
        bo.setFCONTACTUNITTYPE ( payEntity.getTransactionCompanyType () );
        //采购部门
        BaseChildBo procureDept = new BaseChildBo ().setFNumber ( payEntity.getProcureDeptCode () );
        bo.setFPURCHASEDEPTID ( procureDept );
        //往来单位
        BaseChildBo transaction = new BaseChildBo ().setFNumber ( payEntity.getTransactionCompanyCode () );
        bo.setFCONTACTUNIT ( transaction );
        //采购组

        //期望付款日期
        bo.setFBookingDate ( CommonUtil.getDateStrFormat ( payEntity.getExpectedPayTime (), "yyyy-MM-dd HH:mm:ss" ) );
        //采购员
        BaseChildBo purUser = new BaseChildBo ().setFNumber ( payEntity.getPurchaserUserCode () );
        bo.setFPURCHASERID ( purUser );
        //备注
        bo.setFREMARK ( payEntity.getRemarks () );

        //2.明细列表
        List<PayDetail> payDetails = assemblePayDetail ( payEntity.getId () );
        bo.setFPAYBILLENTRY ( payDetails );
        return bo;
    }


    /**
     * 组装付款明细
     * @param payId
     * @return
     */
    private List<PayDetail> assemblePayDetail (String payId) {
        List<PayDetail> payDetails = new ArrayList<> ();
        List<KingFinancePayDetailEntity> list = iKingFinancePayDetailService.list ( new QueryWrapper<KingFinancePayDetailEntity> ().
                eq ( "relation_id", payId ) );
        list.forEach ( payDetail -> {
            PayDetail detail = new PayDetail ();
            //结算方式
            BaseChildBo settleType = new BaseChildBo ().setFNumber ( payDetail.getKingSettlementTypeCode () );
            detail.setFSETTLETYPEID ( settleType );
            //付款用途
            BaseChildBo payPurpose = new BaseChildBo ().setFNumber ( payDetail.getPayReceiptPurposeCode () );
            detail.setFPURPOSEID ( payPurpose );
            //预付项目类型
            detail.setFPAYITEMTYPE ( payDetail.getPrepaidItemType () );
            //应付金额
            detail.setFPAYTOTALAMOUNTFOR ( payDetail.getCopeMoney () );
            //现金折扣
            detail.setFSETTLEDISTAMOUNTFOR ( payDetail.getCashDiscount () );
            //折后金额
            detail.setFSETTLEPAYAMOUNTFOR ( payDetail.getDiscountedMoney () );
            //手续费
            detail.setFHANDLINGCHARGEFOR ( payDetail.getHandlingFees () );
            //长短款
            detail.setFOVERSHORTAGEFOR ( payDetail.getLongShortPay () );
            //我方银行账号
            BaseChildBo account = new BaseChildBo ().setFNumber ( payDetail.getBankNumber () );
            detail.setFACCOUNTID ( account );
            //现金账号

            //备注
            detail.setFCOMMENT ( payDetail.getRemarks () );
            //费用项目
            BaseChildBo cost = new BaseChildBo ().setFNumber ( payDetail.getFeeCode () );
            detail.setFCOSTID ( cost );
            //费用承担部门
            BaseChildBo expenseDept = new BaseChildBo ().setFNumber ( payDetail.getFeeBearDeptCode () );
            detail.setFEXPENSEDEPTID_E ( expenseDept );
            //物料编码

            //含税单价

            //采购订单号
            detail.setFPURCHASEORDERNO ( payDetail.getOrderCode () );
            //税额
            detail.setFTaxAmt ( payDetail.getTaxRate () );
            payDetails.add ( detail );
        } );
        return payDetails;
    }

}
